
import { getLocalStorage, setLocalStorage, queryQueryString } from './util'

// 获取 网络相关耗时
export const getPageBasicTiming = (timing) => {
  const sslTime = timing.secureConnectionStart
  const connectSslTime = sslTime > 0 ? timing.connectEnd - sslTime : 0
  const { entryType, domainLookupEnd, domainLookupStart, connectEnd, connectStart }  = timing
  const ext = {
    entryType: 'navigation',
    name: entryType,
    connectSslTime, // SSL连接耗时
    dns: domainLookupEnd - domainLookupStart, // DNS解析耗时
    connect: connectEnd - connectStart // TCP链接耗时
  }

  return ext
}

// 需要上报的条件
export const resourceLogNeed = function(entry) {
  const { initiatorType, duration, responseStatus, name } = entry
  // 接口请求耗时大于200ms且小于 10s, 或者 状态码非 200 或者 指定的业务接口全量上报
  return (initiatorType === 'xmlhttprequest' && ((duration >= 100 && duration < 10000) || responseStatus != 200 || isAllLog(name))) ||
        (initiatorType === 'script' && duration >= 50)
}

// 收集日志
export const collectLogs = (data = {}) => {
  window.logData.push(caculateSendData(data))
  setLocalStorage('performance-log', window.logData)
}

// 全量上报的接口
export const isAllLog = (url) => {
  if (!url) return false
  return url.includes('/patient_wechat/v1/user/islogined') || url.includes('/token/refresh/confirm') || url.includes('/token/refresh/preview')
}

// 根据trace_id 获取接口的相应信息
export const searchResponseInfo = (request_id) => {
  const _reqMap = window.ajaxLogMap || new Map()
  const _reqInfo = _reqMap.get(request_id)

  _reqMap.delete(request_id)
  // console.log(_reqInfo, '_reqInfo_reqInfo_reqInfo')
  return _reqInfo
}

// 整合上报数据
export const caculateSendData = (data = {}) => {
  const { cid: _cid, package_name, env: _env, user_id: _user_id, platform, os_version } = window.veryLogConfig || {}
  const cat_domain = `${_cid}${package_name}`
  const _extData = Object.assign(data, {
    page_url: location.href
  })
  const _data = {
    index: 'performance',
    user_id: _user_id || '',
    cat_event_name: data.entryType === 'paint' ? data.name : data.entryType,
    cat_event_type: navigator.sendBeacon ? 'sendbeacon' : 'ajax',
    cat_domain,
    channel_id: _cid,
    current_url: location.href.split('?')[0],
    bhv_time: Date.now(), // 产生日志时间戳
    log_level: 'debug', //
    request_type: 1, // 1,普通的接口请求; 2,请求图片
    os_version: os_version,
    platform: platform,
    env: _env
  }
  if (['resource'].includes(data.entryType)) {
    _data.cat_duration = data.duration
    _data.cat_event_name = data.initiatorType

    _data.api_url = data.initiatorType === 'xmlhttprequest' ? data.name?.split('?')[0] : '' // 接口url

    // 接口请求， 将 trace_id 取出
    if (data.initiatorType === 'xmlhttprequest') {
      _data.request_id = queryQueryString(data.name, 'trace_id')
      if (!_user_id) {
        _data.user_id = getLocalStorage('user_id') || ''
      }
      // 指定接口的范返回数据 收集起来
      const resInfo = searchResponseInfo(_data.request_id) || {}
      if (Reflect.has(resInfo, 'resData')) {
        _data.api_code = resInfo.status
        const { resData, status } = resInfo
        if (isAllLog(data.name)) {
          _extData.res_data = resData// 接口的返回值
        } else {
          // 非 200 状态码， 接口返回 异常
          if (status != 200 || resData.result_code == 0 || resData.data === null) {
            _data.log_level = 'warn'
            _extData.res_data = resData || {} // 接口的返回值
          }
        }
      }
    }
  } else {
    _data.cat_duration = data.startTime
  }
  _data.ext = JSON.stringify(_extData)
  return _data
}

// 发送日志
export const sendLog = (mastSend = false) => {
  const _params = window.logData || []
  const _len = _params.length
  if (_len || mastSend) {
    // const sendParams = _params.splice(0, _len) // 直接取出一段上报
    if (navigator.sendBeacon) { // 支持 sendBeacon
      sendBeaconFunc(window.logData, mastSend)
    } else { // 不支持， 就用常规 ajax方式上报
      sendAjaxFunc(window.logData)
    }
  }
}

// sendBeacon 发送数据
export const sendBeaconFunc = (data, mastSend = false) => {
  if (data.length && (data.length >= 10 || mastSend)) {
    const allData = data
    const sendParams = allData.splice(0, 10) // 数据量大了，sendBeacon会失败
    // 服务端只支持 application/json; 数据格式
    try {
      const logBlob = new Blob([JSON.stringify(sendParams)], {
        type: 'application/json; charset=UTF-8'
      })
      const res = navigator.sendBeacon('https://logcollect.91160.com/v2/dev/web?type=performance', logBlob)
      console.log(res, 'sendBeaconFuncsendBeaconFunc')
      // 上报不成功， 使用 ajax 上报
      if (!res) {
        sendAjaxFunc(sendParams)
      } else {
        // sendBeaconFunc(allData)
        sendLog()
      }
    } catch (err) {
      console.log(err, '上报日志函数内部发生错误')
    }
  }
}

// ajax 发送数据
export const sendAjaxFunc = (data) => {
  postAjaxinfo(data).then(res => {
    if (res.code !== 0) {
      // ajax上报失败 存储起来
      saveFailLogs(data)
    }
  }).catch(err => {
    console.log(err)
    // 存储上报失败的 日志
    saveFailLogs(data)
  })
}

// 上报失败，需要把日志存储起来
export const saveFailLogs = (sendLogs) => {
  Promise.resolve(sendLogs).then(data => {
    const _has_saved_log = getLocalStorage('performance-log') || []
    setLocalStorage('performance-log', [..._has_saved_log, ...data])
  })
}

export const postAjaxinfo = (data) => {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest()
    xhr.open('POST', `https://logcollect.91160.com/v2/dev/web?type=performance`)
    xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8')
    xhr.send(JSON.stringify(data))
    xhr.onreadystatechange = () => {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          const res = JSON.parse(xhr.responseText)
          resolve(res)
        } else {
          reject(xhr.status)
        }
      }
    }
  })
}

